package com.summer.data.rs.extractor;

import com.summer.data.dialect.Dialect;
import com.summer.data.exception.BaseException;
import com.summer.data.rs.Extractor;
import com.summer.data.rs.map.*;
import com.summer.data.table.BaseTable;

import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

/**
 * @author 345480567@qq.com
 */

public class OneRecordExtractor<T> implements Extractor<T> {

    private final AbstractResultSetMapFun<T> mapFun;

    private boolean mustOneRecord = false;

    public OneRecordExtractor(AbstractResultSetMapFun<T> mapFun, boolean mustOneRecord) {
        this.mapFun = new ResultSetMapLogFun<T>(mapFun);
        this.mustOneRecord = mustOneRecord;
    }

    @Override
    public T extract(ResultSet rs, Dialect dialect) {

        mapFun.setDialect(dialect);

        try {
            T t = null;
            int c = 0;

            mapFun.mapBegin(rs);
            while (rs.next()) {
                c++;
                if (c>1) {
                    break;
                }
                t = mapFun.map(rs, dialect);
            }
            mapFun.mapEnd(rs);

            if (mustOneRecord) {
                if (c==1) {
                    return t;
                } else {
                    if (c>1) {
                        throw new BaseException("结果集不唯一");
                    } else {
                        throw new BaseException("数据未找到");
                    }
                }
            } else {
                return t;
            }
        } catch (SQLException e) {
            e.printStackTrace();
            throw new BaseException(e);
        }
    }

    public static OneRecordExtractor<Map<String, Object>> createMapExtractor(boolean mustOneRecord) {
        ResultSetToMapFun mapFun = new ResultSetToMapFun();
        return new OneRecordExtractor<Map<String, Object>>(mapFun, mustOneRecord);
    }

    public static <T> OneRecordExtractor<T> createObjectExtractor(Class<T> clazz, boolean mustOneRecord) {
        ResultSetToDtoFun<T> mapFun = new ResultSetToDtoFun<T>(clazz);
        return new OneRecordExtractor<T>(mapFun, mustOneRecord);
    }

    public static <T extends BaseTable> OneRecordExtractor<T> createTableExtractor(Class<T> clazz, boolean mustOneRecord) {
        ResultSetToTableFun<T> mapFun = new ResultSetToTableFun<T>(clazz);
        return new OneRecordExtractor<T>(mapFun, mustOneRecord);
    }

}

